﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Drawing;
using System.Data.Common;
using FmcWebsite.Core;

namespace FmcWebsite.Core
{
    public delegate void AttachmentEvent(Attachment attachment);

    public enum ImageTypes { Jpg, Png, Gif };

    public class Attachment
    {
        private int id;
        private string name;
        private int art_id;
        private string content_type;
        private Stream blob = null;

        public int Id
        {
            get { return id; }
        }

        public string Name
        {
            get { return name; }
        }

        public Stream Blob
        {
            get
            {
                if (blob == null)
                {                    
                    var tbl = DBConnect.Database.Select("SELECT content FROM attachment WHERE attachment_id = " + id.ToString());
                    blob = new MemoryStream((byte[])(tbl.Rows[0]["content"]));
                }
                blob.Position = 0;
                return blob;
            }
        }

        public string ContentType
        {
            get { return content_type; }
        }

        public override string ToString()
        {
            return name;
        }

        /// <summary>
        /// Saving blob to stream
        /// </summary>
        /// <param name="stream">stream to be written</param>
        /// <returns>number of bytes saved in the stream</returns>
        public long Save(Stream stream)
        {
            long total = Blob.Length;
            const int buf_size = 1024 * 1024;
            byte[] buf = new byte[buf_size];
            int read = buf_size;
            while (total > 0) 
            {
                read = Blob.Read(buf, 0, buf_size);
                stream.Write(buf, 0, read);
                total -= read;
            }
            return Blob.Length;
        }

        public event AttachmentEvent DeleteNotification; 

        public void Delete()
        {
            DeleteNotification(this);
            DBConnect.Database.ExecDDL("DELETE FROM attachment WHERE attachment_id = " + id.ToString());
            art_id = -1;
        }

        static private Attachment ByContentType(DataRow row)
        {
            string[] contenttype = row.Field<string>("contenttype").Split('\\');

            Type att_type = Type.GetType("FmcWebsite.Core.Attachment" + contenttype[0].ToUpper());
            Attachment att = (Attachment)Activator.CreateInstance(att_type);
            
            att.name = row.Field<string>("name");
            att.id = row.Field<int>("attachment_id");
            att.content_type = row.Field<string>("contenttype");
            att.art_id = row.Field<int>("art_article_id");
            return att;
        }

        static public IEnumerable<Attachment> ByArticle(Article article)
        {
            var tbl = DBConnect.Database.Select("SELECT attachment_id, art_article_id, contenttype, name  FROM attachment WHERE art_article_id = " + article.Id.ToString());
            foreach (DataRow row in tbl.Rows)
            {
                yield return Attachment.ByContentType(row);
            }
        }

        static public Attachment ById(int att_id)
        {
            var tbl = DBConnect.Database.Select("SELECT attachment_id, art_article_id, contenttype, name FROM attachment WHERE attachment_id=" + att_id.ToString());
            return Attachment.ByContentType(tbl.Rows[0]);
        }

        static public Attachment Insert(Article art, string name, string filename)
        {
            // filling content from file
            byte[] content;
            FileStream file = new FileStream(filename, FileMode.Open);
            content = new byte[file.Length];
            file.Read(content, 0, content.Length);
            file.Close();

            // build parameters
            DbParameter[] parameters = new DbParameter[]
            {
                DBConnect.Database.CreateParameter("@artid", art.Id),
                DBConnect.Database.CreateParameter("@name", name),
                DBConnect.Database.CreateParameter("@contenttype", GetContentType(filename)),
                DBConnect.Database.CreateParameter("@content", content)
            };

            DBConnect.Database.ExecDDL("INSERT INTO attachment (art_article_id, name, contenttype, content) VALUES " +
                "(@artid, @name, @contenttype, @content)", parameters);

            return ById(DBConnect.Database.Select("SELECT MAX(attachment_id) FROM attachment").Rows[0].Field<int>(0));
        }
        
        static protected string GetContentType(string filename)
        {
            FileInfo file = new FileInfo(filename);
            return GetContentType(file);
        }

        static protected string GetContentType(FileInfo fileinfo)
        {
            string ext = fileinfo.Extension.Substring(1);
            // try if it's an image
            if (Enum.GetNames(typeof(ImageTypes)).Where(x => x.Equals(ext, StringComparison.OrdinalIgnoreCase)).Count() > 0)
            {
                return "image\\" + ext;
            }
            return "";
        }        
    }
    
    public class AttachmentIMAGE : Attachment
    {
        private Image image = null;

        public Image Image
        {
            get 
            {
                if ((image == null) && (Blob.Length >0))
                    try
                    {
                        image = Image.FromStream(Blob);
                    }
                    catch
                    {
                        image = null;
                    }
                return image;
            }
        }

        static public IEnumerable<AttachmentIMAGE> GetSlides(bool actualOnly)
        {
            var category = Category.ByCode("SLID");
            var articles = Article.ByCategory(category, true);
            foreach (Article art in articles)
            {
                if (!actualOnly || art.Publish)
                {
                    foreach (AttachmentIMAGE img in art.Images)
                    {
                        yield return img;
                    }
                }
            }
        }

        static public IEnumerable<AttachmentIMAGE> GetSlides()
        {
            return GetSlides(true);
        }
    }

    public class AttachmentAUDIO : Attachment
    {

    }
    
}
